package org.checkboo.hopefullyengine.scenegraph;

import java.util.LinkedList;

import org.checkboo.hopefullyengine.boundingvolumes.Frustum;
import org.checkboo.math.Matrix44f;

public class SceneGraph {

	private GroupNode rootNode;
	private Frustum frustum;
	
	public SceneGraph(GroupNode root){
		this.rootNode = root;
	}
	
	public void compileGraph(){
		rootNode.getWorldTransform().set(rootNode.getLocalTransform());
		compileGroupNode(rootNode);
	}
	
	private void compileGroupNode(GroupNode node){
		Matrix44f world = new Matrix44f();
		for(Node n : node.getChildren()){			
			node.getWorldTransform().multiplyRes(n.getLocalTransform(), world);
			n.getWorldTransform().set(world);
			
			if(n instanceof GeometryNode){
				((GeometryNode)n).updateBound();
			}
			if(n instanceof GroupNode){
				compileGroupNode((GroupNode)n);
				//((GroupNode)n).updateBound();
			}
		}		
		node.updateBound();
	}
	
	
	
	public void getVisibleObjects(Frustum frustum){
		this.frustum = frustum;
		getObjects(rootNode);
	}
	
	private void getObjects(GroupNode node){

		
		for(Node n : node.getChildren()){
			if(n instanceof GeometryNode){
				if(((GeometryNode)n).getBoundingVolume().checkWithViewVolume(this.frustum.getPlanes()))
					n.setRender(true);
				else
					n.setRender(false);
			}
			if(n instanceof GroupNode && null != ((GroupNode)n).getBoundingVolume()){
				if(((GroupNode)n).getBoundingVolume().checkWithViewVolume(this.frustum.getPlanes())){
					n.setRender(true);
					getObjects((GroupNode)n);
				}
				else
					n.setRender(false);
						
			}
		}
		
	}
	
	public LinkedList<LightNode> getLights(){
		return getLightsList(rootNode);		
	}
	
	private LinkedList<LightNode> getLightsList(GroupNode node){
		LinkedList<LightNode> lights = new LinkedList<LightNode>();
		
		for(Node n : node.getChildren()){
			if(n instanceof LightNode)
				lights.add((LightNode)n);
			if(n instanceof GroupNode)
				lights.addAll(getLightsList((GroupNode)n));
		}
		
		return lights;
	}
	
}
